package com.hns.frame.security;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import com.hns.can.base.entity.SysOperateLogEntity;
import com.hns.can.base.entity.SysUserEntity;
import com.hns.can.base.service.LoginService;
import com.hns.can.base.service.SysAuthorityFuncService;
import com.hns.can.base.vo.MenuVo;
import com.hns.tool.pub.PubUtil;
import com.hns.tool.pub.UtilString;

/**
 * 一个自定义的filter,必须包含authenticationManager,accessDecisionManager.
 * securityMetadataSource三个属性， 我们的所有控制将在这三个类中实现
 * @author:Fisher
 * @email:zhuangcaijin@126.com
 * @version Revision 2.0.0
 */
public class AppFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
    
    @Autowired
    private SysAuthorityFuncService sysAuthorityFuncService;
    
    @Autowired
	private LoginService loginService;
    
    private FilterInvocationSecurityMetadataSource securityMetadataSource;
    
    @Override
    public Class<?> getSecureObjectClass() {
        return FilterInvocation.class;
    }
    
    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
        return securityMetadataSource;
    }
    
    @Override
    public void destroy() {
    }
    
    /**
     * 拦截器
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     * @author:Fisher
     * @email:zhuangcaijin@126.com
     */
    @SuppressWarnings("unchecked")
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    	
    	//TODO （临时）防止非功能性访问session重复问题，待修改
//    	Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//    	if(PubUtil.isEmpty(obj) || obj.equals("anonymousUser")){//anonymousUser
//    		request.getRequestDispatcher("/logon/commonSessionExpired.htm").forward(request, response);
//    	}
    	
        FilterInvocation fi = new FilterInvocation(request, response, chain);
        String url = fi.getRequestUrl();
        HttpSession httpSession = fi.getHttpRequest().getSession();
        SysUserEntity user = (SysUserEntity) httpSession.getAttribute("SES_CURRENTUSER");
        
        // 导出excel、pdf的拦截处理：取得请求的当前用户、已经url对应的funcId
        if(url.indexOf("Excel.htm") != -1 || url.indexOf("Pdf.htm") != -1) {
        	String exportUrl = url;
        	if(exportUrl.lastIndexOf("?") != -1) {
        		exportUrl = exportUrl.substring(0, exportUrl.lastIndexOf("?"));
        	}
        	String funcId = sysAuthorityFuncService.getAuthFuncId(exportUrl);
        	request.setAttribute("FUNC_ID", funcId);
        	
        	if(PubUtil.isEmpty(funcId)){
        		request.setAttribute("FUNC_ID", exportUrl);
        	}
        	
        	if(PubUtil.isNotEmpty(user)) {
        		request.setAttribute("USER_ID", user.getId());
        	}
        }
        
        InterceptorStatusToken token = super.beforeInvocation(fi);
        try {
            BigDecimal beginTime = new BigDecimal(System.currentTimeMillis());
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
            BigDecimal endTime = new BigDecimal(System.currentTimeMillis());
            // --------------- 操作日志记录 begin
            List<MenuVo> sysFuncList = (List<MenuVo>) httpSession.getAttribute("SES_ALLAUTHORITY");
            
            if(PubUtil.isNotEmpty(user) && PubUtil.isNotEmpty(sysFuncList)){
                if (url.lastIndexOf("?") != -1) {// 有包含'?'
                    url = url.substring(0, url.lastIndexOf("?"));
                }
                
                if (!"/logon/enter.htm".equals(url) || !"/logon/commonQuit.htm".equals(url)) {// 排除登录和注销
                    for (MenuVo menuVo : sysFuncList) {
                    	String compUrl = menuVo.getUrl();
                        if (compUrl.subSequence(1, compUrl.length()).equals(url)) {
                            String ip = PubUtil.getRemortIP((HttpServletRequest)request);
                            SysOperateLogEntity entity = new SysOperateLogEntity();
                            entity.setLogId(UtilString.getUUID());
                            entity.setCorpId(user.getCorpId());
                            entity.setOprId(user.getId());
                            entity.setMnpltTime(new Date());
                            entity.setMnpltUrl(url);
                            entity.setMnpltDura(endTime.subtract(beginTime));
                            entity.setIpAdr(ip);
//                            ClientMacAddr mac = new ClientMacAddr(ip);
//                            entity.setMacAdr(mac.GetRemoteMacAddr());
                            entity.setMnpltFunc(menuVo.getId());
                            entity.setMnpltType(menuVo.getType());
                            entity.setSystemId("CLOUD_CAN_V2.0");
                            Map<String, Object> params = this.getParameter(request);
                            String parmasStr = JSONObject.fromObject(params).toString();
                            entity.setMnpltCont(parmasStr);
                            loginService.saveSysOperateLog(entity);
                            break;
                        }
                    }
                }
            }
            // --------------- 操作日志记录 end
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            super.afterInvocation(token, null);
        }
    }
    
    @Override
    public void init(FilterConfig config) throws ServletException {
        
    }
    
    public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
        return securityMetadataSource;
    }
    
    public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
        this.securityMetadataSource = securityMetadataSource;
    }
    
    public Map<String, Object> getParameter(ServletRequest request) {
        Map<String, Object> sParaTemp = new LinkedHashMap<String, Object>();
        Map<String, String[]> map = request.getParameterMap();
        Set<Entry<String, String[]>> setEntry = map.entrySet();
        for (Entry<String, String[]> entry : setEntry) {
            String key = entry.getKey();
            String value = entry.getValue()[0];
            sParaTemp.put(key, value);
        }
        return sParaTemp;
    }
}
